package com.xshiwu.service.Impl;

import com.alibaba.fastjson.JSON;
import com.xshiwu.config.ElasticSearchClientConfig;
import com.xshiwu.pojo.Content;
import com.xshiwu.service.ContentService;
import com.xshiwu.utils.ElasticSearchConst;
import com.xshiwu.utils.HtmlParseUtil;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchPhraseQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class ContentServiceImpl implements ContentService {

    @Resource
    private ElasticSearchClientConfig client;

    @Override
    public Boolean parseContent(String keywords) throws IOException {
        // 获取连接对象
        List<Content> list = new HtmlParseUtil().parseJd(keywords);
        // 批量添加
        BulkRequest bulkRequest = new BulkRequest();
        // 设置批量添加的最长时间
        bulkRequest.timeout("10s");
        for (int i = 0; i < list.size(); i++) {
            bulkRequest.add(
                    new IndexRequest(ElasticSearchConst.ES_INDEX)
                            // 获取资源并且转换为json对象
                            .source(JSON.toJSONString(list.get(i)), XContentType.JSON)
            );

        }
        BulkResponse bulks = client.restHighLevelClient().bulk(bulkRequest, RequestOptions.DEFAULT);
        // 返回是否成功，官方的成功默认为false，我们改成了true
        return !bulks.hasFailures();
    }

    /**
     * 分页且高亮查询
     * @param keywords 查询的关键字
     * @param page 分页的页码
     * @param limit 页面的条数
     * @return 将分页功能、搜索功能搜索出来的数据通过map集合转换为高亮字段后添加进list集合
     * @throws IOException IO异常，所有的都有
     */
    @Override
    public List<Map<String, Object>> search(String keywords, Integer page, Integer limit) throws IOException {
        if (page <= 1){
            page = 1;
        }

        // 条件搜索
        SearchRequest request = new SearchRequest(ElasticSearchConst.ES_INDEX);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.timeout(new TimeValue(30, TimeUnit.SECONDS));

        // 分页功能
        sourceBuilder.from(page);
        sourceBuilder.size(limit);

        // 精准匹配
        MatchPhraseQueryBuilder mb = QueryBuilders.matchPhraseQuery("title", keywords);
        sourceBuilder.query(mb);

        // 高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        // 多个高亮显示
        highlightBuilder.requireFieldMatch(false);
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        // 应用高亮设置
        sourceBuilder.highlighter(highlightBuilder);


        request.source(sourceBuilder);
        SearchResponse search = client.restHighLevelClient().search(request, RequestOptions.DEFAULT);
        // 解析结果
        List<Map<String, Object>> list = new ArrayList<>();
        for (SearchHit documentFields : search.getHits().getHits()) {
            // 将所有的结果遍历出来封装到list里面，如果不需要高亮时注释高亮代码，放行list.add(documentFields.getSourceAsMap());
            // list.add(documentFields.getSourceAsMap());
            Map<String, HighlightField> highlightFields = documentFields.getHighlightFields();
            // 获取所有的标题
            HighlightField title = highlightFields.get("title");
            // 获取所有的值取出来
            // 将原来的字段换位我们高亮的字段
            Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();
            if (title != null){
                // 取出高亮字段
                Text[] fragments = title.fragments();
                String newTitle = "";
                // 可变更为StringBuilder newTitle = new StringBuilder();
                for (Text fragment : fragments) {
                    // newTitle.append(fragment)
                    newTitle += fragment;
                }
                // 高亮子弹替换原来的内容
                sourceAsMap.put("title",newTitle);
            }
            list.add(sourceAsMap);
        }
        return list;
    }
}
